package com.houmeiyuan.huiguniang;


import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;
import java.sql.SQLException;


@Configuration
@EnableTransactionManagement
@MapperScan("com.houmeiyuan.huiguniang.modles.dao")
@ComponentScan(basePackages = {"com.houmeiyuan.huiguniang.common"})
public class AppConfig {
    /*配置数据库连接+mybatis*/
    @Value("${datasource.url}")
    private String jdbcUrl;
    @Value("${datasource.username}")
    private String jdbcUsername;
    @Value("${datasource.password}")
    private String jdbcPassword;
    @Value("${datasource.driver-class-name}")
    private String jdbcDrive;
    @Value("${datasource.min-idle}")
    private int jdbcMinIdle;
    @Value("${datasource.pool-size}")
    private int jdbcPoolsize;
    @Value("${mybatis.mapperLocations}")
    private String mapperLocations;
    @Value("${mybatis.config}")
    private String mybatisConfig;


    @Bean(destroyMethod = "close")
    public DataSource dataSource() throws SQLException {

        HikariConfig hikariConfig = new HikariConfig();
        hikariConfig.setDriverClassName(this.jdbcDrive);
        hikariConfig.setJdbcUrl(this.jdbcUrl);
        hikariConfig.setUsername(this.jdbcUsername);
        hikariConfig.setPassword(this.jdbcPassword);
        hikariConfig.setPoolName("springHikariCP");
        hikariConfig.setAutoCommit(false);/*HikariCP在做大数据插入的时候，如果autoCommit=false, 会插入失败：*/
        hikariConfig.addDataSourceProperty("cachePrepStmts", "true");
        hikariConfig.addDataSourceProperty("prepStmtCacheSize", "250");
        hikariConfig.addDataSourceProperty("prepStmtCacheSqlLimit", "20480");
        hikariConfig.addDataSourceProperty("useServerPrepStmts", "true");
        hikariConfig.setMinimumIdle(this.jdbcMinIdle);/*控制连接池空闲连接的最小数量*/
        hikariConfig.setMaximumPoolSize(this.jdbcPoolsize);
        hikariConfig.setConnectionInitSql("SELECT 1");

        HikariDataSource dataSource = new HikariDataSource(hikariConfig);/*Hikar的数据库对象*/

        //新增配置
        dataSource.setIdleTimeout(60000);/*移除空闲连接*/
        dataSource.setConnectionTimeout(60000);/*连接超时*/
        dataSource.setValidationTimeout(3000);/*验证连接有效性的超时时间(*/

        try {
            dataSource.setLoginTimeout(5);/*数据库登录时间*/
        } catch (SQLException e) {
            e.printStackTrace();
        }
        dataSource.setMaxLifetime(60000);/*连接存活时间*/

        return dataSource;
    }

    /*平台服务：SpringBoot注入选择*/
    @Bean
    public PlatformTransactionManager transactionManager() throws SQLException {
        return new DataSourceTransactionManager(dataSource());
    }

    @Bean/*spring容器和mybatis的sqlsessionfactory的数据工厂*/
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
        sessionFactory.setDataSource(dataSource());
        sessionFactory.setMapperLocations(this.getResources(this.mapperLocations));/*Mapper.xml文件检索*/
        sessionFactory.setConfigLocation(this.getResources(this.mybatisConfig)[0]);/*mybatis文件索引*/
        return sessionFactory.getObject();
    }

    /*用于对配置文件检索，找到位置获取文件*/
    private Resource[] getResources(String locations) {
        try {
            PathMatchingResourcePatternResolver pr = new PathMatchingResourcePatternResolver();
            Resource[] res = pr.getResources(locations);
            return res;
        } catch (java.io.IOException e) {
            return null;
        }
    }

}
